package com.wikso.db;

import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

public class DBOperation {

	protected static PreparedStatement getSqlst(Connection conn,
			SqlBean<?> sql, Object[] args) throws Exception {
		PreparedStatement stmt = conn.prepareStatement(sql.getSql());
		if (args == null || args.length == 0) {
			return stmt;
		}
		if (args.length > 1) {
			for (int i = 0; i < args.length; i++) {
				stmt.setObject(i + 1, args[i]);
			}
		}
		// if (args.length == 1)
		Class<?> cls = args[0].getClass();
		String pname = cls.getClass().getName();
		if (pname.indexOf('.') < 0
				|| (!cls.isArray() && pname.startsWith("java.lang."))) {
			stmt.setObject(1, args[0]);
			return stmt;
		}

		if (List.class.isAssignableFrom(cls)) {
			List<?> list = (List<?>) args[0];
			for (int i = 0; i < list.size(); i++) {
				stmt.setObject(i + 1, list.get(i));
			}
			return stmt;
		}
		if (cls.isArray()) {
			Object vals[] = (Object[]) args[0];
			for (int i = 0; i < vals.length; i++) {
				stmt.setObject(i + 1, vals[i]);
			}
			return stmt;
		}
		if (sql.paramName != null && sql.paramName.size() > 0) {
			if (Map.class.isAssignableFrom(cls)) {
				@SuppressWarnings("unchecked")
				Map<String, ?> mapv = (Map<String, ?>) args[0];
				for (int i = 0; i < sql.paramName.size(); i++) {
					stmt.setObject(i + 1, mapv.get(sql.paramName.get(i)));
				}
				return stmt;
			}
		}
		if (sql.paramMethod != null && sql.paramMethod.size() > 0) {
			int leng = sql.paramMethod.size();
			for (int i = 0; i < leng; i++) {
				stmt.setObject(i + 1, sql.paramMethod.get(i).invoke(args[0]));
			}
			return stmt;
		}
		return stmt;
	}

	protected static void close(Statement stmt, ResultSet rs) {
		try {
			if (rs != null)
				rs.close();
			if (stmt != null)
				stmt.close();
		} catch (SQLException e) {
			System.out.println(e.getMessage());
			e.printStackTrace();
		}
	}

	private static HashMap<String, String> insertcolumnsmap = new HashMap<String, String>();

	public static String getColoumnsAsString(String tblName, Connection conn)
			throws SQLException {
		if (insertcolumnsmap.containsKey(tblName)) {
			return insertcolumnsmap.get(tblName);
		}
		Statement stmt = conn.createStatement();
		ResultSet res = stmt.executeQuery("select * from " + tblName
				+ " where 1=2");
		ResultSetMetaData rmd = res.getMetaData();
		int count = rmd.getColumnCount();
		StringBuffer sb = new StringBuffer(",");
		for (int i = 0; i < count; i++) {
			sb.append(rmd.getColumnLabel(i + 1).toLowerCase()).append(',');
		}
		String str = sb.toString();
		insertcolumnsmap.put(tblName, sb.toString());
		res.close();
		stmt.close();
		return str;
	}

	protected static Object getRsObject(ResultSet rs, int i, Class<?> cls)
			throws SQLException {
		if (cls == String.class) {
			return rs.getString(i);
		}
		if (cls == Integer.class || cls == int.class) {
			return rs.getInt(i);
		}
		if (cls == Long.class || cls == long.class) {
			return rs.getLong(i);
		}
		if (cls == short.class || cls == Short.class) {
			return rs.getShort(i);
		}
		if (cls == Date.class) {
			return rs.getTimestamp(i);
		}
		if (cls == Float.class || cls == float.class) {
			return rs.getFloat(i);
		}
		if (cls == char.class || cls == Character.class) {
			return rs.getString(i).charAt(0);
		}
		if (cls == boolean.class || cls == Boolean.class) {
			String val = rs.getString(i);
			return val.equalsIgnoreCase("true") || val.equals("1") ? true
					: false;
		}
		return rs.getObject(i);
	}

	@SuppressWarnings("unchecked")
	protected static <E> E getEle(SqlBean<E> sql, int w, ResultSetMetaData md,
			ResultSet rs) throws Exception {
		Class<E> cls = sql.returnType;
		if (cls == null || Map.class.isAssignableFrom(cls)) {
			Map<String, Object> map;
			if (cls != null && cls.isInterface()) {
				map = new HashMap<String, Object>();
			} else {
				map = (Map<String, Object>) cls.newInstance();
			}
			for (int i = 1; i <= w; i++) {
				String lab = md.getColumnLabel(i);
				map.put(lab, rs.getObject(i));
			}
			return (E) map;
		}

		String name = cls.getName();
		if (w == 1
				&& (name.indexOf('.') < 0 || (!cls.isArray() && name
						.startsWith("java.lang.")))) {
			return (E) getRsObject(rs, 1, cls);
		}

		if (cls.isArray()) {
			String n = cls.getSimpleName();
			if (n.equals("String[]")) {
				String[] row = new String[w];
				for (int i = 1; i <= w; i++) {
					row[i - 1] = rs.getString(i);
				}
				return (E) row;
			}
			if (n.equals("int[]")) {
				int[] row = new int[w];
				for (int i = 1; i <= w; i++) {
					row[i - 1] = rs.getInt(i);
				}
				return (E) row;
			}
			if (n.equals("long[]")) {
				long[] row = new long[w];
				for (int i = 1; i <= w; i++) {
					row[i - 1] = rs.getLong(i);
				}
				return (E) row;
			}
			throw new Exception("unsurport type:" + cls.getSimpleName());
		}
		if (List.class.isAssignableFrom(cls)) {
			LinkedList<Object> row = new LinkedList<Object>();
			for (int i = 1; i <= w; i++) {
				row.addLast(rs.getObject(i));
			}
			return (E) row;
		}
		E ele = cls.newInstance();
		LinkedList<Method> ms = sql.getResultMethod(md);
		for (int i = 1; i <= w; i++) {
			Object v = getRsObject(rs, i, ms.get(i - 1).getParameterTypes()[0]);
			ms.get(i - 1).invoke(ele, v);
		}
		return ele;
	}

	public final static Object[] NullObject = new Object[] {};

}
